package util;

import com.yyx.anno.Autowired;
import com.yyx.anno.Component;
import com.yyx.anno.Qualifier;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AnnotationConfigApplicationContext {

    Map<String,Object> map = new HashMap<String,Object>();

    public Object scan(String basePackage) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String rootPath = this.getClass().getResource("/").getPath();
        String basePackagePath = basePackage.replaceAll("\\.","\\\\");
        File file = new File(rootPath+"//"+basePackagePath);
        String names[]=file.list();
        Object object=null;
        String beanName=null;
        for (String name:names){
            name=name.replaceAll(".class","");
           Class clazz= Class.forName(basePackage+"."+name);
           beanName=GenerateBeanName(clazz);
           //判断是否有@Component,如果加了，实例化出来,并放入map
            if(clazz.isAnnotationPresent(Component.class)){
                 object=clazz.newInstance();
                map.put(beanName,object);
            }

            //判断是否有依赖，得到所有属性
            Field fields[] = clazz.getDeclaredFields();
            for(Field field : fields){
                //判断属性上是否有@Autowired 这里模仿byType
                if(field.isAnnotationPresent(Autowired.class)){
                    String flag="byType";
                    String injectObjectName="";
                    //是否含有Qualifier注解，若有，注入方式变为byName
                    if(field.isAnnotationPresent(Qualifier.class)){
                        Annotation annotation=field.getAnnotation(Qualifier.class);
                        if(((Qualifier) annotation).value().equals("")){
                            //得到属性类型名字，比如String aa =>field.getName()=> aa
                            injectObjectName = field.getName();
                        }else {
                            injectObjectName=((Qualifier) annotation).value();
                        }
                        flag="byName";
                    }

                    if(flag.equals("byType")){
                        //得到属性类型，比如String aa =>field.getType()=String.class
                        Class injectObjectClazz = field.getType();
                        //由于bytype 所以需要遍历map当中的所有对象
                        //判断对象的类型是否和injectObjectClazz相同
                        int count = 0;
                        Object injectObject = null;
                        for (String key : map.keySet()) {
                            Class temp = map.get(key).getClass().getInterfaces()[0];
                            if (temp.getName().equals(injectObjectClazz.getName())) {
                                injectObject = map.get(key);
                                //记录找到一个，因为可能找到多个count
                                count++;
                            }
                        }

                        if (count > 1) {
                            throw new SpringException("需要一个对象，但是找到了两个对象");
                        } else {
                            //实例化并注入
                            object = clazz.newInstance();
                            field.setAccessible(true);
                            field.set(object, injectObject);
                        }
                    }else if(flag.equals("byName")){

                        //由于byName 所以需要遍历标签当中的id
                        //通过id获得injectObject
                        Object injectObject=null;
                        for (String key:map.keySet()){
                            if(key.equals(injectObjectName)){
                                injectObject=map.get(key);
                            }
                        }
                        //注入object里
                        object = clazz.newInstance();
                        field.setAccessible(true);
                        field.set(object, injectObject);

                    }

                }
            }
        }


        return object;

    }

    /**
     * 生成beanName
     * @param clazz
     * @return
     */
    private String GenerateBeanName(Class clazz){
        return clazz.getSimpleName();
    }

}
